package org.wmq.taskschedule.algorithm;

import org.opencv.core.Mat;
import org.opencv.core.Size;
import org.opencv.imgproc.Imgproc;

/**
 * 形态学操作算法执行器
 * 实现AlgorithmExecutor接口，用于对图像进行形态学操作
 */
public class MorphologicalOperationExecutor implements AlgorithmExecutor {

    private int operationType; // 操作类型
    private int kernelSize; // 核大小
    private int iterations; // 迭代次数
    private String description; // 算法描述

    /**
     * 默认构造函数，使用默认参数
     */
    public MorphologicalOperationExecutor() {
        this.operationType = Imgproc.MORPH_DILATE;
        this.kernelSize = 3;
        this.iterations = 1;
        this.description = "形态学操作算法 - 对图像进行膨胀操作";
    }

    /**
     * 构造函数，允许自定义参数
     * 
     * @param operationType 操作类型
     * @param kernelSize 核大小
     * @param iterations 迭代次数
     */
    public MorphologicalOperationExecutor(int operationType, int kernelSize, int iterations) {
        if (kernelSize % 2 == 0 || kernelSize <= 1) {
            throw new IllegalArgumentException("核大小必须是奇数且大于1");
        }
        this.operationType = operationType;
        this.kernelSize = kernelSize;
        this.iterations = iterations;
        this.description = getOperationDescription(operationType);
    }

    /**
     * 构造函数，允许自定义所有参数
     * 
     * @param operationType 操作类型
     * @param kernelSize 核大小
     * @param iterations 迭代次数
     * @param description 算法描述
     */
    public MorphologicalOperationExecutor(int operationType, int kernelSize, int iterations, String description) {
        if (kernelSize % 2 == 0 || kernelSize <= 1) {
            throw new IllegalArgumentException("核大小必须是奇数且大于1");
        }
        this.operationType = operationType;
        this.kernelSize = kernelSize;
        this.iterations = iterations;
        this.description = description;
    }

    @Override
    public Mat execute(Mat input) {
        if (input == null || input.empty()) {
            throw new IllegalArgumentException("输入图像不能为空");
        }

        // 创建输出图像
        Mat output = new Mat();

        // 创建结构元素
        Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(kernelSize, kernelSize));

        // 应用形态学操作
        Imgproc.morphologyEx(input, output, operationType, kernel, new org.opencv.core.Point(-1, -1), iterations);

        // 释放中间资源
        kernel.release();

        return output;
    }

    /**
     * 获取操作类型描述
     * 
     * @param operationType 操作类型
     * @return 描述文本
     */
    private String getOperationDescription(int operationType) {
        switch (operationType) {
            case Imgproc.MORPH_ERODE:
                return "形态学操作算法 - 对图像进行腐蚀操作";
            case Imgproc.MORPH_DILATE:
                return "形态学操作算法 - 对图像进行膨胀操作";
            case Imgproc.MORPH_OPEN:
                return "形态学操作算法 - 对图像进行开操作（先腐蚀后膨胀）";
            case Imgproc.MORPH_CLOSE:
                return "形态学操作算法 - 对图像进行闭操作（先膨胀后腐蚀）";
            case Imgproc.MORPH_GRADIENT:
                return "形态学操作算法 - 对图像进行梯度操作（膨胀减去腐蚀）";
            case Imgproc.MORPH_TOPHAT:
                return "形态学操作算法 - 对图像进行顶帽操作（原图减去开操作）";
            case Imgproc.MORPH_BLACKHAT:
                return "形态学操作算法 - 对图像进行黑帽操作（闭操作减去原图）";
            default:
                return "形态学操作算法";
        }
    }

    // Getters and setters
    public int getOperationType() {
        return operationType;
    }

    public void setOperationType(int operationType) {
        this.operationType = operationType;
        if (this.description == null || this.description.startsWith("形态学操作算法")) {
            this.description = getOperationDescription(operationType);
        }
    }

    public int getKernelSize() {
        return kernelSize;
    }

    public void setKernelSize(int kernelSize) {
        if (kernelSize % 2 == 0 || kernelSize <= 1) {
            throw new IllegalArgumentException("核大小必须是奇数且大于1");
        }
        this.kernelSize = kernelSize;
    }

    public int getIterations() {
        return iterations;
    }

    public void setIterations(int iterations) {
        this.iterations = iterations;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
}